package com.xing.lei.happy.thrid.flh;


import com.alibaba.fastjson.JSONObject;
import com.xing.lei.happy.thrid.flh.util.CryptUtils;
import com.xing.lei.happy.thrid.flh.util.SHA1;

import javax.swing.Timer;
import javax.swing.*;
import java.awt.*;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.*;
import java.sql.*;
import java.util.List;
import java.util.*;

/**
 * Description:公卫健康档案项目中authorization.wadata的加密解密工具类
 * 解密：authorization.wadata -> json格式的txt文件
 * 加密：数据库或json格式的txt文件 -> authorization.wadata
 *
 * @author flh
 * @version 1.00
 * @Date 2023/1/17
 */
public class AuthorizationUtil {

    // 使用JSON文件存储最近使用的数据
    private static final String HISTORY_FILE = "temp.json";
    private static final String DB_URL_HISTORY = "db_url_history";
    private static final String DB_USERNAME_HISTORY = "db_username_history";
    private static final String DB_PASSWORD_HISTORY = "db_password_history";
    private static final String KEY_HISTORY = "key_history";
    private static final String LAST_DB_URL = "last_db_url";
    private static final String LAST_DB_USERNAME = "last_db_username";
    private static final String LAST_DB_PASSWORD = "last_db_password";
    private static final String LAST_KEY = "last_key";
    private static final int MAX_HISTORY = 5;

    // 数据库URL的默认示例值
    private static final String DEFAULT_DB_URL = "jdbc:oracle:thin:@//localhost:1521/orcl";

    public static void main(String[] args){
        showMainMenu();
    }

    public static void showMainMenu() {
        // 让用户选择操作类型
        String[] options = {"解密", "加密"};
        int choice = JOptionPane.showOptionDialog(null,
                "请选择操作类型：",
                "MD5加密工具",
                JOptionPane.YES_NO_OPTION,
                JOptionPane.QUESTION_MESSAGE,
                null,
                options,
                options[0]);

        if (choice == 0) {
            // 解密
            decryptAuthorization();
        } else if (choice == 1) {
            // 加密
            encryptAuthorization();
        } else {
            System.out.println("操作已取消");
            System.exit(0); // 直接退出程序
        }
    }

    public static void decryptAuthorization(){
        decryptAuthorization(null, null);
    }

    public static void decryptAuthorization(String previousPath, String previousKey){
        System.out.println("--------------------开始解密---------------------");

        // 获取默认路径
        String path_def = (new File("")).getAbsolutePath() + File.separator;
        String defaultPath = path_def + "authorization.wadata";

        // 如果有之前的路径，则使用之前的路径
        if (previousPath != null && !previousPath.isEmpty()) {
            defaultPath = previousPath;
        }

        // 创建输入面板
        JPanel panel = new JPanel();
        panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));

        // 文件选择面板
        JPanel filePanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
        JTextField pathField = new JTextField(defaultPath, 20);
        pathField.setEditable(false); // 不允许直接修改
        JButton browseButton = new JButton("浏览");
        filePanel.add(new JLabel("授权文件:"));
        filePanel.add(pathField);
        filePanel.add(browseButton);

        // 密钥输入（带历史记录的ComboBox）
        JPanel keyPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
        JComboBox<String> keyComboBox = new JComboBox<>();
        keyComboBox.setEditable(true);
        keyComboBox.setPreferredSize(new Dimension(200, 25));

        // 加载密钥历史记录
        loadHistoryToComboBox(keyComboBox, KEY_HISTORY, LAST_KEY, previousKey);

        keyPanel.add(new JLabel("文件密钥:"));
        keyPanel.add(keyComboBox);

        panel.add(filePanel);
        panel.add(keyPanel);

        // 文件选择器
        JFileChooser fileChooser = new JFileChooser();
        fileChooser.setFileFilter(new javax.swing.filechooser.FileFilter() {
            @Override
            public boolean accept(File f) {
                return f.getName().toLowerCase().endsWith(".wadata") || f.isDirectory();
            }

            @Override
            public String getDescription() {
                return "授权文件 (*.wadata)";
            }
        });

        // 默认选中默认路径文件
        File defaultFile = new File(defaultPath);
        if (defaultFile.exists()) {
            fileChooser.setSelectedFile(defaultFile);
        } else {
            fileChooser.setCurrentDirectory(new File(path_def));
        }

        browseButton.addActionListener(e -> {
            int returnVal = fileChooser.showOpenDialog(panel);
            if (returnVal == JFileChooser.APPROVE_OPTION) {
                File file = fileChooser.getSelectedFile();
                // 校验文件后缀
                if (!file.getName().toLowerCase().endsWith(".wadata")) {
                    JOptionPane.showMessageDialog(panel, "请选择 .wadata 后缀的授权文件！");
                    return;
                }
                pathField.setText(file.getAbsolutePath());
            }
        });

        // 添加确认按钮面板
        JPanel buttonPanel = new JPanel(new FlowLayout());
        JButton okButton = new JButton("确定");
        JButton cancelButton = new JButton("取消");
        buttonPanel.add(okButton);
        buttonPanel.add(cancelButton);

        panel.add(buttonPanel);

        // 创建对话框
        JDialog dialog = new JDialog();
        dialog.setTitle("请输入解密信息");
        dialog.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
        dialog.setResizable(false);
        dialog.add(panel);
        dialog.pack();
        dialog.setLocationRelativeTo(null);
        dialog.setVisible(true);

        // 添加窗口关闭事件处理（直接关闭程序）
        dialog.addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent e) {
                dialog.dispose();
                System.out.println("解密操作已取消");
                System.exit(0); // 直接退出程序
            }
        });

        // 取消按钮事件（直接返回主菜单）
        cancelButton.addActionListener(e -> {
            dialog.dispose();
            System.out.println("解密操作已取消");
            showMainMenu(); // 直接返回主菜单
        });

        // 确定按钮事件
        okButton.addActionListener(e -> {
            String path = pathField.getText().trim();
            String key = keyComboBox.getEditor().getItem().toString();

            if (path.isEmpty()) {
                JOptionPane.showMessageDialog(dialog, "文件路径不能为空！");
                return;
            }

            // 校验文件后缀
            if (!path.toLowerCase().endsWith(".wadata")) {
                JOptionPane.showMessageDialog(dialog, "文件后缀不正确，请选择 .wadata 文件！");
                return;
            }

            if (key == null || key.trim().isEmpty()) {
                JOptionPane.showMessageDialog(dialog, "密钥不能为空！");
                return;
            }

            // 确保key不为null
            key = key.replaceAll("\\s*|\r|\n|\t","");

            //检查文件是否存在
            File file = new File(path);
            if (!file.exists()) {
                JOptionPane.showMessageDialog(dialog, "路径错误，授权文件未找到！");
                return;
            }

            // 禁用按钮防止重复点击
            okButton.setEnabled(false);
            cancelButton.setEnabled(false);
            browseButton.setEnabled(false);

            // 添加处理中提示
            JLabel processingLabel = new JLabel("正在解密...");
            processingLabel.setAlignmentX(Component.CENTER_ALIGNMENT);
            panel.add(Box.createVerticalStrut(10));
            panel.add(processingLabel);
            panel.revalidate();
            panel.repaint();

            // 动态更新省略号
            Timer timer = new Timer(500, evt -> {
                String text = processingLabel.getText();
                if (text.endsWith("...")) {
                    processingLabel.setText("正在解密");
                } else {
                    processingLabel.setText(text + ".");
                }
            });
            timer.start();

            // 在新线程中执行解密操作
            String finalKey = key;
            SwingWorker<Boolean, Void> worker = new SwingWorker<Boolean, Void>() {
                private String errorMessage = "";

                @Override
                protected Boolean doInBackground() throws Exception {
                    FileInputStream fileInputStream = null;
                    RandomAccessFile randomAccessFile = null;

                    try {
                        //解密
                        Properties properties = new Properties();
                        fileInputStream = new FileInputStream(file);
                        properties.load(fileInputStream);
                        String auth_de = null;
                        auth_de = CryptUtils.decrypt(properties.getProperty("authorization"), SHA1.encrypt(finalKey));
                        //格式化为标准json字符串
                        auth_de = auth_de.replaceAll("[^0-9A-Za-z,:\"{}_]","").replace("{","{\n").replace("}","\n}").replace(",",",\n");
                        //输出到文件
                        randomAccessFile = new RandomAccessFile(path_def + "authorization.txt", "rw");
                        //覆盖写
                        randomAccessFile.setLength(0);
                        randomAccessFile.write(auth_de.getBytes());
                        return true;
                    } catch (Exception e) {
                        errorMessage = e.getMessage();

                        // 检查是否是密钥错误导致的解密失败
                        if (e instanceof RuntimeException && e.getCause() instanceof javax.crypto.BadPaddingException) {
                            errorMessage = "密钥错误！请检查您输入的密钥是否正确。";
                        } else if (errorMessage != null && errorMessage.contains("BadPaddingException")) {
                            errorMessage = "密钥错误！请检查您输入的密钥是否正确。";
                        }
                        return false;
                    } finally {
                        // 释放资源
                        if (fileInputStream != null) {
                            try {
                                fileInputStream.close();
                            } catch (IOException e) {
                                e.printStackTrace();
                            }
                        }
                        if (randomAccessFile != null) {
                            try {
                                randomAccessFile.close();
                            } catch (IOException e) {
                                e.printStackTrace();
                            }
                        }
                    }
                }

                @Override
                protected void done() {
                    timer.stop(); // 停止动态省略号

                    // 移除处理中提示
                    panel.remove(processingLabel);
                    panel.revalidate();
                    panel.repaint();

                    // 保存密钥历史
                    saveHistory(KEY_HISTORY, LAST_KEY, finalKey);

                    dialog.dispose(); // 关闭对话框

                    try {
                        Boolean success = get();
                        if (success) {
                            JOptionPane.showMessageDialog(null, "输出解密后文件：" + path_def + "authorization.txt");
                            System.out.println("--------------------解密成功---------------------");
                            showMainMenu(); // 只有成功完成才返回主菜单
                        } else {
                            JOptionPane.showMessageDialog(null, "解密过程中发生错误: " + errorMessage);
                            // 出错后保留现场信息返回解密界面
                            decryptAuthorization(path, finalKey);
                        }
                    } catch (Exception e) {
                        JOptionPane.showMessageDialog(null, "解密过程中发生未知错误: " + e.getMessage());
                        e.printStackTrace();
                        decryptAuthorization(path, finalKey);
                    }
                }
            };

            worker.execute();
        });
    }

    public static void encryptAuthorization(){
        encryptAuthorization(null, null, null, null, null);
    }

    public static void encryptAuthorization(String previousJsonPath, String previousKey,
                                            String previousDbUrl, String previousDbUsername,
                                            String previousDbPassword){
        System.out.println("--------------------开始加密---------------------");

        // 获取默认路径
        String path_def = (new File("")).getAbsolutePath() + File.separator;
        String defaultInputPath = path_def + "authorization.txt";

        // 如果有之前的路径，则使用之前的路径
        if (previousJsonPath != null && !previousJsonPath.isEmpty()) {
            defaultInputPath = previousJsonPath;
        }

        // 创建输入面板
        JPanel panel = new JPanel();
        panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
        panel.setPreferredSize(new Dimension(500, 350));

        // 数据源选择
        JPanel sourcePanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
        ButtonGroup sourceGroup = new ButtonGroup();
        JRadioButton fileRadio = new JRadioButton("JSON文件", true);
        JRadioButton dbRadio = new JRadioButton("数据库");
        sourceGroup.add(fileRadio);
        sourceGroup.add(dbRadio);
        sourcePanel.add(new JLabel("数据源:"));
        sourcePanel.add(fileRadio);
        sourcePanel.add(dbRadio);

        // JSON文件选择面板
        JPanel filePanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
        filePanel.setMaximumSize(new Dimension(Integer.MAX_VALUE, 30));
        JTextField inputPathField = new JTextField(defaultInputPath, 30);
        inputPathField.setEditable(false); // 不允许直接修改
        JButton browseButton = new JButton("浏览");
        filePanel.add(new JLabel("JSON文件:"));
        filePanel.add(inputPathField);
        filePanel.add(browseButton);

        // 数据库连接面板
        JPanel dbPanel = new JPanel();
        dbPanel.setLayout(new BoxLayout(dbPanel, BoxLayout.Y_AXIS));
        dbPanel.setBorder(BorderFactory.createTitledBorder("数据库连接信息"));
        dbPanel.setMaximumSize(new Dimension(Integer.MAX_VALUE, 150));

        // 统一标签宽度和输入框长度
        Dimension labelDimension = new Dimension(80, 25);
        Dimension fieldDimension = new Dimension(300, 25);

        // 数据库URL（带历史记录的ComboBox）
        JComboBox<String> dbUrlComboBox = new JComboBox<>();
        dbUrlComboBox.setEditable(true);
        dbUrlComboBox.setPreferredSize(fieldDimension);

        // 加载数据库URL历史记录，如果没有历史记录则使用默认值
        loadHistoryToComboBox(dbUrlComboBox, DB_URL_HISTORY, LAST_DB_URL, previousDbUrl);
        if (dbUrlComboBox.getItemCount() == 0) {
            dbUrlComboBox.addItem(DEFAULT_DB_URL);
            dbUrlComboBox.setSelectedItem(DEFAULT_DB_URL);
        }

        // 数据库用户名（带历史记录的ComboBox）
        JComboBox<String> dbUsernameComboBox = new JComboBox<>();
        dbUsernameComboBox.setEditable(true);
        dbUsernameComboBox.setPreferredSize(fieldDimension);

        // 加载数据库用户名历史记录
        loadHistoryToComboBox(dbUsernameComboBox, DB_USERNAME_HISTORY, LAST_DB_USERNAME, previousDbUsername);

        // 数据库密码（带历史记录的ComboBox）
        JComboBox<String> dbPasswordComboBox = new JComboBox<>();
        dbPasswordComboBox.setEditable(true);
        dbPasswordComboBox.setPreferredSize(fieldDimension);

        // 加载数据库密码历史记录
        loadHistoryToComboBox(dbPasswordComboBox, DB_PASSWORD_HISTORY, LAST_DB_PASSWORD, previousDbPassword);

        // 设置统一尺寸
        JLabel urlLabel = new JLabel("数据库URL:");
        urlLabel.setPreferredSize(labelDimension);

        JLabel userLabel = new JLabel("用户名:");
        userLabel.setPreferredSize(labelDimension);

        JLabel passLabel = new JLabel("密码:");
        passLabel.setPreferredSize(labelDimension);

        JPanel dbUrlPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
        dbUrlPanel.setMaximumSize(new Dimension(Integer.MAX_VALUE, 30));
        dbUrlPanel.add(urlLabel);
        dbUrlPanel.add(dbUrlComboBox);

        JPanel dbUserPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
        dbUserPanel.setMaximumSize(new Dimension(Integer.MAX_VALUE, 30));
        dbUserPanel.add(userLabel);
        dbUserPanel.add(dbUsernameComboBox);

        JPanel dbPassPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
        dbPassPanel.setMaximumSize(new Dimension(Integer.MAX_VALUE, 30));
        dbPassPanel.add(passLabel);
        dbPassPanel.add(dbPasswordComboBox);

        dbPanel.add(dbUrlPanel);
        dbPanel.add(dbUserPanel);
        dbPanel.add(dbPassPanel);
        dbPanel.setVisible(false); // 默认隐藏数据库面板

        // 切换数据源显示
        fileRadio.addActionListener(ev -> {
            filePanel.setVisible(true);
            dbPanel.setVisible(false);
            panel.revalidate();
            panel.repaint();
        });

        dbRadio.addActionListener(ev -> {
            filePanel.setVisible(false);
            dbPanel.setVisible(true);
            panel.revalidate();
            panel.repaint();
        });

        // 密钥输入（带历史记录的ComboBox）
        JPanel keyPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
        keyPanel.setMaximumSize(new Dimension(Integer.MAX_VALUE, 30));
        JComboBox<String> keyComboBox = new JComboBox<>();
        keyComboBox.setEditable(true);
        keyComboBox.setPreferredSize(fieldDimension);

        // 加载密钥历史记录
        loadHistoryToComboBox(keyComboBox, KEY_HISTORY, LAST_KEY, previousKey);

        JLabel keyLabel = new JLabel("加密密钥:");
        // 稍微减小标签宽度，给输入框留出更多空间，实现右移效果
        keyLabel.setPreferredSize(new Dimension(labelDimension.width + 5, labelDimension.height));


        keyPanel.add(keyLabel);
        keyPanel.add(keyComboBox);

        // 添加确认按钮面板
        JPanel buttonPanel = new JPanel(new FlowLayout());
        JButton okButton = new JButton("确定");
        JButton cancelButton = new JButton("取消");
        buttonPanel.add(okButton);
        buttonPanel.add(cancelButton);

        panel.add(Box.createVerticalStrut(5));
        panel.add(sourcePanel);
        panel.add(Box.createVerticalStrut(5));
        panel.add(filePanel);
        panel.add(dbPanel);
        panel.add(Box.createVerticalStrut(5));
        panel.add(keyPanel);
        panel.add(Box.createVerticalStrut(10));
        panel.add(buttonPanel);
        panel.add(Box.createVerticalGlue());

        // 文件选择器
        JFileChooser fileChooser = new JFileChooser();
        fileChooser.setFileFilter(new javax.swing.filechooser.FileFilter() {
            @Override
            public boolean accept(File f) {
                return f.getName().toLowerCase().endsWith(".txt") || f.isDirectory();
            }

            @Override
            public String getDescription() {
                return "JSON文件 (*.txt)";
            }
        });

        // 默认选中默认路径文件
        File defaultFile = new File(defaultInputPath);
        if (defaultFile.exists()) {
            fileChooser.setSelectedFile(defaultFile);
        } else {
            fileChooser.setCurrentDirectory(new File(path_def));
        }

        browseButton.addActionListener(ev -> {
            int returnVal = fileChooser.showOpenDialog(panel);
            if (returnVal == JFileChooser.APPROVE_OPTION) {
                File file = fileChooser.getSelectedFile();
                // 校验文件后缀
                if (!file.getName().toLowerCase().endsWith(".txt")) {
                    JOptionPane.showMessageDialog(panel, "请选择 .txt 后缀的JSON文件！");
                    return;
                }
                inputPathField.setText(file.getAbsolutePath());
            }
        });

        // 创建包含滚动面板的主面板
        JScrollPane scrollPane = new JScrollPane(panel);
        scrollPane.setPreferredSize(new Dimension(550, 400));

        // 创建对话框
        JDialog dialog = new JDialog();
        dialog.setTitle("请输入加密信息");
        dialog.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
        dialog.setResizable(false);
        dialog.add(scrollPane);
        dialog.pack();
        dialog.setLocationRelativeTo(null);
        dialog.setVisible(true);

        // 添加窗口关闭事件处理（直接关闭程序）
        dialog.addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent e) {
                dialog.dispose();
                System.out.println("加密操作已取消");
                System.exit(0); // 直接退出程序
            }
        });

        // 取消按钮事件（直接返回主菜单）
        cancelButton.addActionListener(e -> {
            dialog.dispose();
            System.out.println("加密操作已取消");
            showMainMenu(); // 直接返回主菜单
        });

        // 确定按钮事件
        okButton.addActionListener(e -> {
            String key = keyComboBox.getEditor().getItem().toString();

            // 禁用按钮防止重复点击
            okButton.setEnabled(false);
            cancelButton.setEnabled(false);
            browseButton.setEnabled(false);
            fileRadio.setEnabled(false);
            dbRadio.setEnabled(false);

            // 添加处理中提示
            JLabel processingLabel = new JLabel("正在加密...");
            processingLabel.setAlignmentX(Component.CENTER_ALIGNMENT);
            panel.add(Box.createVerticalStrut(10));
            panel.add(processingLabel);
            panel.revalidate();
            panel.repaint();

            // 动态更新省略号
            Timer timer = new Timer(500, evt -> {
                String text = processingLabel.getText();
                if (text.endsWith("...")) {
                    processingLabel.setText("正在加密");
                } else {
                    processingLabel.setText(text + ".");
                }
            });
            timer.start();

            // 在新线程中执行加密操作
            SwingWorker<Boolean, Void> worker = new SwingWorker<Boolean, Void>() {
                private String errorMessage = "";
                private String jsonData = "";

                @Override
                protected Boolean doInBackground() throws Exception {
                    BufferedReader bufferedReader = null;
                    FileOutputStream fileOutputStream = null;

                    try {
                        if (fileRadio.isSelected()) {
                            // 从JSON文件读取数据
                            String inputPath = inputPathField.getText().trim();

                            if (inputPath.isEmpty()) {
                                errorMessage = "文件路径不能为空！";
                                return false;
                            }

                            // 校验文件后缀
                            if (!inputPath.toLowerCase().endsWith(".txt")) {
                                errorMessage = "文件后缀不正确，请选择 .txt 文件！";
                                return false;
                            }

                            //检查输入文件是否存在
                            File inputFile = new File(inputPath);
                            if (!inputFile.exists()) {
                                errorMessage = "路径错误，JSON文件未找到！";
                                return false;
                            }

                            //读取JSON内容
                            StringBuilder jsonContent = new StringBuilder();
                            bufferedReader = new BufferedReader(new FileReader(inputFile));
                            String line;
                            while ((line = bufferedReader.readLine()) != null) {
                                jsonContent.append(line);
                            }
                            jsonData = jsonContent.toString();
                        } else {
                            // 从数据库读取数据
                            String dbUrl = dbUrlComboBox.getEditor().getItem().toString().trim();
                            String dbUsername = dbUsernameComboBox.getEditor().getItem().toString().trim();
                            String dbPassword = dbPasswordComboBox.getEditor().getItem().toString().trim(); // 密码不隐藏

                            if (dbUrl.isEmpty() || dbUsername.isEmpty() || dbPassword.isEmpty()) {
                                errorMessage = "数据库连接信息不能为空！";
                                return false;
                            }

                            if (!dbUrl.startsWith("jdbc:oracle:")) {
                                errorMessage = "目前只支持Oracle数据库！";
                                return false;
                            }

                            try {
                                // 指定的查询语句
                                String dbQuery = "SELECT qxdm FROM xt_qxxx ORDER BY ID";

                                // 尝试连接数据库并执行查询
                                Class.forName("oracle.jdbc.driver.OracleDriver");
                                Connection conn = DriverManager.getConnection(dbUrl, dbUsername, dbPassword);
                                Statement stmt = conn.createStatement();
                                ResultSet rs = stmt.executeQuery(dbQuery);

                                // 根据查询出的qxdm拼装JSON，key是qxdm，value固定"true"
                                StringBuilder jsonBuilder = new StringBuilder();
                                jsonBuilder.append("{");

                                boolean first = true;
                                while (rs.next()) {
                                    if (!first) {
                                        jsonBuilder.append(",");
                                    }
                                    String qxdm = rs.getString("qxdm");
                                    if (qxdm != null) {
                                        jsonBuilder.append("\"").append(qxdm).append("\":\"true\"");
                                        first = false;
                                    }
                                }

                                jsonBuilder.append("}");
                                jsonData = jsonBuilder.toString();

                                rs.close();
                                stmt.close();
                                conn.close();
                            } catch (ClassNotFoundException ex) {
                                errorMessage = "未找到Oracle数据库驱动，请确认已安装Oracle JDBC驱动！";
                                return false;
                            } catch (SQLException ex) {
                                errorMessage = "数据库连接或查询出错: " + ex.getMessage();
                                return false;
                            }
                        }

                        if (key == null || key.trim().isEmpty()) {
                            errorMessage = "密钥不能为空！";
                            return false;
                        }
                        // 确保key不为null
                        String cleanKey = key.replaceAll("\\s*|\r|\n|\t","");

                        //压缩JSON格式（移除换行和多余空格）
                        String compressedJson = jsonData.replaceAll("\\s+", "");

                        //使用DES加密
                        String encryptedData = CryptUtils.encrypt(compressedJson, SHA1.encrypt(cleanKey));

                        //创建Properties对象并保存
                        Properties properties = new Properties();
                        properties.setProperty("authorization", encryptedData);

                        //输出到文件
                        String outputPath = path_def + "authorization.wadata";
                        File outputFile = new File(outputPath);
                        if (outputFile.exists()) {
                            outputFile.delete();
                        }
                        outputFile.createNewFile();

                        fileOutputStream = new FileOutputStream(outputFile);
                        properties.store(fileOutputStream, "Encrypted authorization file");

                        return true;
                    } catch (Exception ex) {
                        errorMessage = "加密过程中发生错误: " + ex.getMessage();
                        ex.printStackTrace();
                        return false;
                    } finally {
                        // 释放资源
                        if (bufferedReader != null) {
                            try {
                                bufferedReader.close();
                            } catch (IOException ex) {
                                ex.printStackTrace();
                            }
                        }
                        if (fileOutputStream != null) {
                            try {
                                fileOutputStream.close();
                            } catch (IOException ex) {
                                ex.printStackTrace();
                            }
                        }
                    }
                }

                @Override
                protected void done() {
                    // 停止动态省略号并移除处理中提示
                    timer.stop();

                    // 移除处理中提示
                    panel.remove(processingLabel);
                    panel.revalidate();
                    panel.repaint();

                    // 批量保存所有历史记录，避免多次读写冲突
                    Map<String, Object> historyData = loadHistoryData();

                    if (dbRadio.isSelected()) {
                        String dbUrl = dbUrlComboBox.getEditor().getItem().toString().trim();
                        String dbUsername = dbUsernameComboBox.getEditor().getItem().toString().trim();
                        String dbPassword = dbPasswordComboBox.getEditor().getItem().toString().trim();

                        // 保存数据库URL历史
                        updateHistoryInMap(historyData, DB_URL_HISTORY, LAST_DB_URL, dbUrl);

                        // 保存数据库用户名历史
                        updateHistoryInMap(historyData, DB_USERNAME_HISTORY, LAST_DB_USERNAME, dbUsername);

                        // 保存数据库密码历史
                        updateHistoryInMap(historyData, DB_PASSWORD_HISTORY, LAST_DB_PASSWORD, dbPassword);
                    }

                    // 保存密钥历史
                    updateHistoryInMap(historyData, KEY_HISTORY, LAST_KEY, key.trim());

                    // 一次性保存所有历史数据
                    saveHistoryData(historyData);

                    // 更新ComboBox中的历史记录
                    updateComboBoxHistory(dbUrlComboBox, DB_URL_HISTORY, LAST_DB_URL,
                            dbUrlComboBox.getEditor().getItem().toString());
                    updateComboBoxHistory(dbUsernameComboBox, DB_USERNAME_HISTORY, LAST_DB_USERNAME,
                            dbUsernameComboBox.getEditor().getItem().toString());
                    updateComboBoxHistory(dbPasswordComboBox, DB_PASSWORD_HISTORY, LAST_DB_PASSWORD,
                            dbPasswordComboBox.getEditor().getItem().toString());
                    updateComboBoxHistory(keyComboBox, KEY_HISTORY, LAST_KEY, key);

                    // 不关闭对话框，以便在出错时保留界面状态

                    try {
                        Boolean success = get();
                        if (success) {
                            dialog.dispose(); // 成功时关闭对话框
                            JOptionPane.showMessageDialog(null, "输出加密后文件：" + path_def + "authorization.wadata");
                            System.out.println("--------------------加密成功---------------------");
                            showMainMenu(); // 只有成功完成才返回主菜单
                        } else {
                            // 出错时保留界面状态，但确保显示正确的数据源面板
                            if (dbRadio.isSelected()) {
                                filePanel.setVisible(false);
                                dbPanel.setVisible(true);
                            } else {
                                filePanel.setVisible(true);
                                dbPanel.setVisible(false);
                            }
                            JOptionPane.showMessageDialog(dialog, errorMessage);
                            // 重新启用按钮
                            okButton.setEnabled(true);
                            cancelButton.setEnabled(true);
                            browseButton.setEnabled(true);
                            fileRadio.setEnabled(true);
                            dbRadio.setEnabled(true);
                        }
                    } catch (Exception ex) {
                        // 出错时保留界面状态，但确保显示正确的数据源面板
                        if (dbRadio.isSelected()) {
                            filePanel.setVisible(false);
                            dbPanel.setVisible(true);
                        } else {
                            filePanel.setVisible(true);
                            dbPanel.setVisible(false);
                        }
                        JOptionPane.showMessageDialog(dialog, "加密过程中发生未知错误: " + ex.getMessage());
                        ex.printStackTrace();
                        // 重新启用按钮
                        okButton.setEnabled(true);
                        cancelButton.setEnabled(true);
                        browseButton.setEnabled(true);
                        fileRadio.setEnabled(true);
                        dbRadio.setEnabled(true);
                    }
                }
            };

            worker.execute();
        });
    }

    /**
     * 确认关闭对话框
     * @param dialog 要关闭的对话框
     */
    private static void confirmCloseDialog(JDialog dialog) {
        // 移除原来的确认弹窗，直接关闭对话框
        dialog.dispose();
        showMainMenu(); // 返回主菜单
    }

    /**
     * 从JSON文件加载历史记录到ComboBox
     * @param comboBox 要加载历史记录的ComboBox
     * @param historyKey 历史记录的键
     * @param lastKey 上次值的键
     * @param previousValue 前一个值（如果有）
     */
    private static void loadHistoryToComboBox(JComboBox<String> comboBox, String historyKey, String lastKey, String previousValue) {
        // 获取历史记录
        Map<String, Object> historyData = loadHistoryData();
        List<String> historyList = new ArrayList<>();
        if (historyData.containsKey(historyKey)) {
            Object historyObj = historyData.get(historyKey);
            if (historyObj instanceof List) {
                historyList = (List<String>) historyObj;
            }
        }

        // 获取上次的值
        String lastValue = "";
        if (historyData.containsKey(lastKey)) {
            lastValue = (String) historyData.get(lastKey);
        }
        if (previousValue != null && !previousValue.isEmpty()) {
            lastValue = previousValue;
        }

        // 清空现有项
        comboBox.removeAllItems();

        // 创建一个去重的列表来保存所有项
        Set<String> uniqueItems = new LinkedHashSet<>();

        // 如果有lastValue，先添加它
        if (!lastValue.isEmpty()) {
            uniqueItems.add(lastValue);
        }

        // 添加所有历史记录项
        for (String item : historyList) {
            if (item != null && !item.isEmpty()) {
                uniqueItems.add(item);
            }
        }

        // 将所有唯一项添加到ComboBox中
        for (String item : uniqueItems) {
            comboBox.addItem(item);
        }

        // 设置选中项
        if (!lastValue.isEmpty()) {
            comboBox.setSelectedItem(lastValue);
        } else if (comboBox.getItemCount() > 0) {
            comboBox.setSelectedIndex(0);
        }

        // 确保下拉列表能显示所有项
        comboBox.setMaximumRowCount(Math.max(comboBox.getItemCount(), 1));
    }

    /**
     * 保存历史记录到JSON文件
     * @param historyKey 历史记录的键
     * @param lastKey 上次值的键
     * @param value 要保存的值
     */
    private static void saveHistory(String historyKey, String lastKey, String value) {
        if (value == null || value.isEmpty()) {
            return;
        }

        // 加载现有历史数据
        Map<String, Object> historyData = loadHistoryData();

        // 保存为上次值
        historyData.put(lastKey, value);

        // 获取现有历史记录
        List<String> historyList = new ArrayList<>();
        if (historyData.containsKey(historyKey)) {
            Object historyObj = historyData.get(historyKey);
            if (historyObj instanceof List) {
                historyList = (List<String>) historyObj;
            }
        } else {
            // 如果键不存在，初始化为空列表
            historyData.put(historyKey, historyList);
        }

        // 移除已存在的相同值（确保去重）
        historyList.removeIf(item -> item != null && item.equals(value));

        // 将新值添加到列表开头
        historyList.add(0, value);

        // 限制最多保存5个历史记录
        if (historyList.size() > MAX_HISTORY) {
            historyList = historyList.subList(0, MAX_HISTORY);
        }

        // 保存历史记录
        historyData.put(historyKey, historyList);

        // 写入文件
        saveHistoryData(historyData);
    }

    /**
     * 加载历史数据
     * @return 历史数据Map
     */
    private static Map<String, Object> loadHistoryData() {
        Map<String, Object> historyData = new HashMap<>();
        // 获取默认路径
        String path_def = (new File("")).getAbsolutePath() + File.separator;
        File historyFile = new File(path_def + HISTORY_FILE);

        if (!historyFile.exists()) {
            return historyData;
        }

        try (BufferedReader reader = new BufferedReader(new FileReader(historyFile))) {
            StringBuilder jsonContent = new StringBuilder();
            String line;
            while ((line = reader.readLine()) != null) {
                jsonContent.append(line);
            }

            if (jsonContent.length() > 0) {
                // 简单的JSON解析（实际项目中建议使用JSON库如Gson或Jackson）
                historyData = JSONObject.parseObject(jsonContent.toString());
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

        return historyData;
    }

    /**
     * 保存历史数据
     * @param historyData 历史数据Map
     */
    private static void saveHistoryData(Map<String, Object> historyData) {
        try (FileWriter writer = new FileWriter((new File("")).getAbsolutePath() + File.separator + HISTORY_FILE)) {
            // 简单的JSON序列化（实际项目中建议使用JSON库如Gson或Jackson）
            String json = serializeToJson(historyData);
            writer.write(json);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 简单的JSON序列化方法
     * @param data 要序列化的数据
     * @return JSON字符串
     */
    private static String serializeToJson(Map<String, Object> data) {
        StringBuilder json = new StringBuilder("{");
        boolean first = true;

        for (Map.Entry<String, Object> entry : data.entrySet()) {
            if (!first) {
                json.append(",");
            }

            json.append("\"").append(entry.getKey()).append("\":");

            Object value = entry.getValue();
            if (value instanceof String) {
                json.append("\"").append(value).append("\"");
            } else if (value instanceof List) {
                json.append("[");
                List<String> list = (List<String>) value;
                for (int i = 0; i < list.size(); i++) {
                    if (i > 0) {
                        json.append(",");
                    }
                    // 确保列表中的每个项都是字符串
                    json.append("\"").append(list.get(i) != null ? list.get(i) : "").append("\"");
                }
                json.append("]");
            } else {
                json.append("\"").append(value != null ? value : "").append("\"");
            }

            first = false;
        }

        json.append("}");
        return json.toString();
    }

    /**
     * 更新ComboBox中的历史记录显示
     * @param comboBox 要更新的ComboBox
     * @param historyKey 历史记录的键
     * @param lastKey 上次值的键
     * @param currentValue 当前值
     */
    private static void updateComboBoxHistory(JComboBox<String> comboBox, String historyKey, String lastKey, String currentValue) {
        // 保存当前选中项
        Object selectedItem = comboBox.getSelectedItem();

        // 清空现有项
        comboBox.removeAllItems();

        // 重新加载历史记录
        loadHistoryToComboBox(comboBox, historyKey, lastKey, currentValue);

        // 恢复选中项
        if (selectedItem != null) {
            comboBox.setSelectedItem(selectedItem);
        }

        // 确保下拉列表能显示所有项
        comboBox.setMaximumRowCount(Math.max(comboBox.getItemCount(), 1));
    }

    /**
     * 在历史数据Map中更新特定字段的历史记录
     * @param historyData 历史数据Map
     * @param historyKey 历史记录列表的键
     * @param lastKey 最后值的键
     * @param value 要保存的值
     */
    private static void updateHistoryInMap(Map<String, Object> historyData, String historyKey, String lastKey, String value) {
        // 保存为上次值
        historyData.put(lastKey, value != null ? value : "");

        // 如果值不为空，则更新历史记录列表
        if (value != null && !value.isEmpty()) {
            // 获取现有历史记录
            List<String> historyList = new ArrayList<>();
            if (historyData.containsKey(historyKey)) {
                Object historyObj = historyData.get(historyKey);
                if (historyObj instanceof List) {
                    historyList = (List<String>) historyObj;
                }
            }

            // 移除已存在的相同值（确保去重）
            historyList.removeIf(item -> item != null && item.equals(value));

            // 将新值添加到列表开头
            historyList.add(0, value);

            // 限制最多保存5个历史记录
            if (historyList.size() > MAX_HISTORY) {
                historyList = historyList.subList(0, MAX_HISTORY);
            }

            // 保存历史记录
            historyData.put(historyKey, historyList);
        }
        // 如果值为空，保持现有历史记录不变
    }
}
